/*
 * Created by JFormDesigner on Wed Dec 14 08:06:13 PST 2011
 */

package com.thirdnf.calendar;

import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.awt.*;
import java.awt.event.*;
import java.beans.Beans;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;


/**
 * TODO - need to clean up and add parsing of the date field.
 *
 * @author Joshua Gerth
 */
@SuppressWarnings({"UnusedDeclaration"})
public class DateField extends JPanel
{
    @SuppressWarnings({"UnusedDeclaration"})
    private static final Logger logger = Logger.getLogger(DateField.class);

    private final JPopupMenu _popupMenu;

    private DateTimeFormatter _dateTimeFormatter;

    private Month _month;


    public DateField()
    {
        initComponents();

        _popupMenu = new JPopupMenu();

        _popupMenu.setLightWeightPopupEnabled(true);

        _month = new Month();
        _month.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                LocalDate date = (LocalDate) (evt.getNewValue());
                setDate(date);
                _popupMenu.setVisible(false);
            }
        });

        _popupMenu.add(_month);

        // Go with the basic formatter for the US
        setDateFormatter(DateTimeFormat.forPattern("MMM dd, yyyy"));
    }


    public void setDate(@Nullable LocalDate date)
    {
        _dateField.setForeground(Color.black);

        if (date == null) {
            _dateField.setText("");
        }
        else {
            _dateField.setText(date.toString(_dateTimeFormatter));
        }
    }


    public LocalDate getDate()
    {
        if (Beans.isDesignTime()) { return new LocalDate(); }

        String dateString = _dateField.getText().trim();
        if (dateString.isEmpty()) {
            return new LocalDate();
        }

        LocalDate date = _dateTimeFormatter.parseDateTime(dateString).toLocalDate();

        logger.debug("Parsed date: " + date);

        return date;
    }


    /**
     * Set the date time formatter for the text field.
     *
     * @param formatter (not null) New formatter
     */
    public void setDateFormatter(@NotNull DateTimeFormatter formatter)
    {
        _dateTimeFormatter = formatter;
    }


    /**
     * Handle the user clicking on the button.  This parses the date and gives the popup.
     */
    private void handleMouseClicked() {

        // Figure out what date is in there
        try {
            LocalDate date = _dateTimeFormatter.parseDateTime(_dateField.getText().trim()).toLocalDate();

            logger.debug("Parsed date: " + date);

            _month.setDate(date);
        } catch (IllegalArgumentException exception) {
            // Okay, never mind, just set to today's date

            logger.debug("Unable to parse date, using today's date");
            _month.setDate(new LocalDate());
        }

        // Compute location ... mostly copied from JCalendar
        int x = _calendarLabelButton.getWidth() - (int) _popupMenu.getPreferredSize().getWidth();
        int y = _calendarLabelButton.getY() + _calendarLabelButton.getHeight();

        _popupMenu.show(_calendarLabelButton, x, y);
    }


    private void handleKeyTyped(KeyEvent e) {

        JTextField source = (JTextField) e.getSource();
        char c = e.getKeyChar();

        String text = source.getText();

        if (Character.isDefined(c)) {
            text += c;
        }

        // Empty strings are okay
        if (text.length() == 0) {
            source.setForeground(Color.black);
            return;
        }

        // Assume that every format is going to be at least 5 characters long, ex: M/d/y
        if (text.length() < 5) {
            source.setForeground(Color.red);
            return;
        }

        try {
            // Try to parse it
            _dateTimeFormatter.parseDateTime(text);

            // All is good
            source.setForeground(Color.black);
        }
        catch (IllegalArgumentException exception) {
            source.setForeground(Color.red);
        }
    }


    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        _dateField = new JTextField();
        _calendarLabelButton = new JLabel();

        //======== this ========
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

        //---- _dateField ----
        _dateField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                handleKeyTyped(e);
            }
        });
        add(_dateField);

        //---- _calendarLabelButton ----
        _calendarLabelButton.setIcon(new ImageIcon(getClass().getResource("/calendarIcon.png")));
        _calendarLabelButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                handleMouseClicked();
            }
        });
        add(_calendarLabelButton);
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }


    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    private JTextField _dateField;
    private JLabel _calendarLabelButton;
    // JFormDesigner - End of variables declaration  //GEN-END:variables
}
